package dbpedia;

import zclTool.*;
import java.io.*;
import java.util.regex.*;

import java.util.*;
import java.util.Map.*;

//print the tree of Dbpedia ontology

class OntologyTreeNode {
	String name;
	String fathername;
	String pathToRoot;
	OntologyTreeNode father;
	List<OntologyTreeNode> sons = new ArrayList<OntologyTreeNode>();

	List<String> rphInfobox = new ArrayList<String>();
	int height;

	public static void setHeight(OntologyTreeNode root) {
		setHeight(root, 0);

	}

	public void getPathToRoot() {
		this.pathToRoot = this.name;
		OntologyTreeNode otn = this;
		while (otn.father != null) {
			if (!otn.father.name.equals("Thing")) {
				this.pathToRoot += "-->" + otn.father.name;
			}
			otn = otn.father;
		}
	}

	private static void setHeight(OntologyTreeNode node, int level) {
		node.height = level;
		for (OntologyTreeNode son : node.sons) {
			setHeight(son, level + 1);
		}
	}

	public static String printTree(OntologyTreeNode root) {
		return printTree(root, 0);
	}

	private static String printTree(OntologyTreeNode node, int level) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < level; i++)
			sb.append("\t");
		sb.append(node.height + "  " + node.name + "============>>>>>>>>>>\t");
		for (String a : node.rphInfobox) {
			sb.append(a + ", ");
		}
		sb.append("\n");
		for (OntologyTreeNode son : node.sons) {
			sb.append(printTree(son, level + 1));
		}
		return sb.toString();
	}
}

public class DP_Ontology_Tree {

	/**
	 * @param args
	 */
	// static List<OntologyTreeNode> treenodes = new
	// ArrayList<OntologyTreeNode>();
	HashMap<String, OntologyTreeNode> treenodes = new HashMap<String, OntologyTreeNode>();
	OntologyTreeNode root = new OntologyTreeNode();

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		DP_Ontology_Tree dot = new DP_Ontology_Tree();
		dot.load("dbpedia_3.4.owl");
		System.out.println(dot.toString());
		System.out.println(dot.treenodes.size());
	}

	public void load(String file) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(
				new FileInputStream(file), "utf-8"));
		StringBuffer sb = new StringBuffer();

		String line = "";

		while ((line = br.readLine()) != null) {
			sb.append(line);
		}
		br.close();
		findClass(sb.toString());
	}

	private void findClass(String s) throws Exception {
		root.name = "Thing";
		treenodes.put(root.name, root);
		// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
		// "my0318\\temp_ontology_tree"));
		Pattern p = Pattern
				.compile("<owl:Class rdf:about=\"http://dbpedia.org/ontology/([^\"]*)\">(.*?)</owl:Class>");
		HashSet<String> hs = new HashSet<String>();
		Matcher m = p.matcher(s);
		while (m.find()) {
			String name = m.group(1);
			String rdfs = m.group(2);
			Pattern prdfs = Pattern
					.compile("<rdfs:subClassOf rdf:resource=\"http://dbpedia.org/ontology/([^\"]*)\"/>");
			Matcher mrdfs = prdfs.matcher(rdfs);

			if (mrdfs.find()) {
				String subclassof = mrdfs.group(1);
				// System.out.println(name + "\t" + subclassof);
				{// add an otn into the tree
					OntologyTreeNode otn = new OntologyTreeNode();
					otn.name = name;
					otn.fathername = subclassof;
					treenodes.put(otn.name, otn);
				}
			} else {
				{// add an otn into the tree
					OntologyTreeNode otn = new OntologyTreeNode();
					otn.name = name;
					otn.fathername = "Thing";
					treenodes.put(otn.name, otn);
				}
			}
		}

		Iterator<Entry<String, OntologyTreeNode>> it = treenodes.entrySet()
				.iterator();
		while (it.hasNext()) {
			Entry<String, OntologyTreeNode> e = it.next();
			OntologyTreeNode otn = e.getValue();
			String fathername = otn.fathername;
			if (fathername != null) {
				OntologyTreeNode fathernode = treenodes.get(fathername);
				otn.father = fathernode;
				fathernode.sons.add(otn);
			}
		}

		it = treenodes.entrySet().iterator();
		while (it.hasNext()) {
			Entry<String, OntologyTreeNode> e = it.next();
			OntologyTreeNode otn = e.getValue();
			otn.getPathToRoot();
		}
		OntologyTreeNode.setHeight(root);
		// System.out.println(OntologyTreeNode.printTree(root));
	}

	public String toString() {

		return OntologyTreeNode.printTree(root);
	}

	public boolean areTheyDescendant(String child, String ancestor) {
		OntologyTreeNode otn = this.treenodes.get(child);
		if (otn != null) {
			while (otn.father != null) {
				if (otn.fathername.equals(ancestor)) {
					return true;
				} else {
					otn = otn.father;
				}
			}
		}
		return false;
	}

	// merge the classes into non-parent-son relation, for example, given
	// Person, Artist, Place; return Artist, Place
	public List<String> mergePath(String[] classes) {
		ArrayList<String> result = new ArrayList<String>();
		for (int i = 0; i < classes.length; i++) {
			boolean addToResult = true;
			String a = classes[i];
			for (int j = 0; j < classes.length; j++) {

				String b = classes[j];
				if (areTheyDescendant(b, a)) {
					addToResult = false;
				}
			}
			if (addToResult) {
				OntologyTreeNode otn = this.treenodes.get(a);
				result.add(otn.pathToRoot);
			}
		}
		return result;
	}

	public void mapRaphInfoboxOntoTree(
			HashMap<String, List<String>> infobox_onto) {
		Iterator<Entry<String, List<String>>> it = infobox_onto.entrySet()
				.iterator();
		while (it.hasNext()) {
			Entry<String, List<String>> e = it.next();
			String rphinfo = e.getKey();
			List<String> ontos = e.getValue();
			for (String onto : ontos) {
				OntologyTreeNode otn = this.treenodes.get(onto);
				otn.rphInfobox.add(rphinfo);
			}
		}
	}
}
